#include <Arduino.h>
#include <WiFi.h>
#include <BleCombo.h>
#include <FastLED.h>
#include <Keypad.h>
#include <map>

/*BleComboKeyboard Keyboard("ESP32蓝牙键鼠","哇哇哇哇哇哇哇哇");*/
/** 摇杆相关声明 **/
const int xAxis = 35;         // joystick X axis
const int yAxis = 34;         // joystick Y axis
const int joystick_btn = 18;         // joystick btn
bool joystick_btn_state = 0;         // joystick btn
int range = 48;               // X或Y的输出范围
int threshold = range / 4;    // resting threshold 静息阈
int center = range / 2;       // 静止位置值
int mouseSpeed = 1;  //鼠标速度


#define EC1_UP      1
#define EC1_DOWN    2
#define EC2_UP      3
#define EC2_DOWN    4
#define EC3_UP      5
#define EC3_DOWN    6
/** 旋钮1相关声明 **/
int EC11_A_1 = 23; //旋钮1 A
int EC11_B_1 = 22;//旋钮2 A
bool EC11_1_state;
bool EC11_A_1_CW;   // 转向判据1
bool EC11_B_1_CW;   // 转向判据2

/** 旋钮2相关声明 **/
int EC11_A_2 = 21; //旋钮1 2
int EC11_B_2 = 19;//旋钮2 2
bool EC11_2_state;
bool EC11_A_2_CW;   // 转向判据1
bool EC11_B_2_CW;   // 转向判据2

/** 旋钮3相关声明 **/
int EC11_A_3 = 16; //旋钮1 2
int EC11_B_3 = 17;//旋钮2 2
bool EC11_3_state;
bool EC11_A_3_CW;   // 转向判据1
bool EC11_B_3_CW;   // 转向判据2

#define VOLUME_UP    1
#define VOLUME_DOWN  2

/** 按键相关声明 **/
const byte ROWS = 3; //矩阵键盘行数
const byte COLS = 4; //矩阵键盘列数
//按键定义
char hexaKeys[ROWS][COLS] = {
        {'b', '1', '2', '3'},
        {'a', '4', '5', '6'},
        {'c', '7', '8', '9'},

};


byte rowPins[ROWS] = {32, 33, 25}; //行的针脚连接的接口，第一行连9脚，第二行连8脚。。。
byte colPins[COLS] = {26, 27, 14, 5}; //列的针脚连接的接口，第一列连5脚，第二列连4脚。。。
Keypad kpd = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
unsigned long loopCount;
unsigned long startTime;
String msg;

#define NUM_LEDS 9            // LED灯珠数量
#define LED_DT 13                // Arduino输出控制信号引脚
#define LED_TYPE WS2812         // LED灯带型号
#define COLOR_ORDER GRB         // RGB灯珠中红色、绿色、蓝色LED的排列顺序

uint8_t max_bright = 128;       // LED亮度控制变量，可使用数值为 0 ～ 255， 数值越大则光带亮度越高

CRGB leds[NUM_LEDS];            // 建立光带leds

uint8_t beginHue = 0;
uint8_t deltaHue = 1;


uint8_t type = 0;

//旋钮相关定义
void onECRotate() {
    switch (type) {
        case EC1_UP :
            Keyboard.write(KEY_MEDIA_VOLUME_UP);
            Serial.println("BleKeyboard.1+");
            type = 0;
            break;
        case EC1_DOWN :
            Keyboard.write(KEY_MEDIA_VOLUME_DOWN);
            type = 0;
            Serial.println("BleKeyboard.1-");
            break;
        case EC2_UP:
            Keyboard.write(KEY_MEDIA_VOLUME_UP);
            type = 0;
            break;
        case EC2_DOWN:
            Keyboard.write(KEY_MEDIA_VOLUME_DOWN);
            type = 0;
            break;
        case EC3_UP:
            Keyboard.write(KEY_MEDIA_VOLUME_UP);
            type = 0;
            break;
        case EC3_DOWN:
            Keyboard.write(KEY_MEDIA_VOLUME_DOWN);
            type = 0;
            break;
        default:
            break;
    }

};

void OnKeyPress(char key) {
    switch (key) {
        case 'b':

            break;
        case 'a':

            break;
        case 'c':

            break;
        case '1':

            break;
        case '2':

            break;
        case '3':

            break;
        case '4':

            break;
        case '5':

            break;
        case '6':

            break;
        case '7':

            break;
        case '8':

            break;
        case '9':

            break;
        default:
            break;
    };

}

void handleInterrupt_A() {
    if (EC11_1_state == 0 && digitalRead(EC11_A_1) == LOW) {
        EC11_B_1_CW = digitalRead(EC11_B_1);
        EC11_1_state = !EC11_1_state;
    }
    if (EC11_1_state == 1 && digitalRead(EC11_A_1) == HIGH) {//正转
        EC11_A_1_CW = !digitalRead(EC11_B_1);
        if (EC11_A_1_CW == 1 && EC11_B_1_CW == 1) {
            type = EC1_DOWN;

            Serial.println("BleKeyboard.1");
        }
        if (EC11_A_1_CW == 0 && EC11_B_1_CW == 0) {
            type = EC1_UP;

            Serial.println("BleKeyboard.2");
        }
        EC11_1_state = !EC11_1_state;
    }
}

void handleInterrupt_B() {
    if (EC11_2_state == 0 && digitalRead(EC11_A_2) == LOW) {
        EC11_B_2_CW = digitalRead(EC11_B_2);
        EC11_2_state = !EC11_2_state;
    }
    if (EC11_2_state == 1 && digitalRead(EC11_A_2) == HIGH) {//正转
        EC11_A_2_CW = !digitalRead(EC11_B_2);
        if (EC11_A_2_CW == 1 && EC11_B_2_CW == 1) {
            type = EC2_DOWN;
            Serial.println("BleKeyboard.1");
        }
        if (EC11_A_2_CW == 0 && EC11_B_2_CW == 0) {
            type = EC2_UP;

            Serial.println("BleKeyboard.2");
        }
        EC11_2_state = !EC11_2_state;
    }
}

void handleInterrupt_C() {
    if (EC11_3_state == 0 && digitalRead(EC11_A_3) == LOW) {
        EC11_B_3_CW = digitalRead(EC11_B_3);
        EC11_3_state = !EC11_3_state;
    }
    if (EC11_3_state == 1 && digitalRead(EC11_A_3) == HIGH) {//正转
        EC11_A_3_CW = !digitalRead(EC11_B_3);
        if (EC11_A_3_CW == 1 && EC11_B_3_CW == 1) {
            type = EC3_DOWN;
            Serial.println("BleKeyboard.1");
        }
        if (EC11_A_3_CW == 0 && EC11_B_3_CW == 0) {
            type = EC3_UP;
            Serial.println("BleKeyboard.2");
        }
        EC11_3_state = !EC11_3_state;
    }
}


//摇杆数据的处理
int readAxis1(int thisAxis) {
    // read the analog input:
    int reading = analogRead(thisAxis);
    //Serial.print("xReading xReading: ");Serial.println(analogRead(thisAxis));
    // map the reading from the analog input range to the output range:
    reading = map(reading, 0, 4095, -50, 50);

    // if the output reading is outside from the
    // rest position threshold,  use it:
    //减小数据抖动
    int shakePosition = 25;
    int distance = reading;
    distance -= shakePosition;
//    if(distance>0){
//        distance-=shakePosition;
//    } else{
//        distance+=shakePosition;
//    }
    if (abs(distance) < 20) {
        distance = 0;
    }

    // return the distance for this axis:
    return distance;
}

int readAxis(int thisAxis) {
    // read the analog input:
    int reading = analogRead(thisAxis);

    // map the reading from the analog input range to the output range:
    reading = map(reading, 0, 4095, 0, range);

    // if the output reading is outside from the
    // rest position threshold,  use it:
    int distance = reading - center;

    if (abs(distance) < threshold) {
        distance = 0;
    }

    // return the distance for this axis:
    return distance;
}


void setup() {
    Serial.begin(9600);
    Keyboard.begin();
    Mouse.begin();
    loopCount = 0;
    startTime = millis();
    msg = "";

    pinMode(joystick_btn, INPUT_PULLUP);
    pinMode(EC11_A_1, INPUT_PULLUP);
    pinMode(EC11_B_1, INPUT_PULLUP);
    pinMode(EC11_A_2, INPUT_PULLUP);
    pinMode(EC11_B_2, INPUT_PULLUP);
    pinMode(EC11_A_3, INPUT_PULLUP);
    pinMode(EC11_B_3, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(EC11_A_1), handleInterrupt_A, CHANGE);
    attachInterrupt(digitalPinToInterrupt(EC11_A_2), handleInterrupt_B, CHANGE);
    attachInterrupt(digitalPinToInterrupt(EC11_A_3), handleInterrupt_C, CHANGE);
    LEDS.addLeds<LED_TYPE, LED_DT, COLOR_ORDER>(leds, NUM_LEDS);  // 初始化光带

    FastLED.setBrightness(max_bright);

    Serial.println("BleKeyboard.begin");

}

void loop() {
    if (Keyboard.isConnected()) {
     
        onECRotate();
        //fill_rainbow(leds, NUM_LEDS, beginHue, deltaHue);
        fill_gradient(leds, 0, CHSV(50, 255,255) , NUM_LEDS, CHSV(150,255,255),LONGEST_HUES);
        FastLED.show();
        loopCount++;
        int xAxisValue = readAxis(xAxis) / 5;
        int yAxisValue = readAxis(yAxis) / 5;
//        Serial.print("x:");
//        Serial.println(xAxisValue);
//        Serial.print("y:");
//        Serial.println(yAxisValue);
        Mouse.move(xAxisValue * mouseSpeed, yAxisValue * mouseSpeed);
        if (!digitalRead(joystick_btn)) {
            Serial.println("摇杆按键按下");
            Mouse.click(MOUSE_LEFT);
            delay(350);
        } else {


        }


        if (xAxisValue != 0) {
            Serial.print("x: ");
            Serial.println(xAxisValue);
            if (xAxisValue > 0) {

            } else {

            }
        }
        if (yAxisValue != 0) {
            Serial.println("y: ");
            Serial.println(yAxisValue);
            if (yAxisValue > 0) {

            } else {

            }
        }


        if ((millis() - startTime) > 5000) {
            Serial.print("平均每秒循环次数：");
            Serial.println(loopCount / 5);
            startTime = millis();
            loopCount = 0;
        }

//     Fills kpd.key[ ] array with up-to 10 active keys.
//     Returns true if there are ANY active keys.
        if (kpd.getKeys()) {
            for (int i = 0; i < LIST_MAX; i++)   // Scan the whole key list.
            {
                if (kpd.key[i].stateChanged)   // Only find keys that have changed state.
                {
                    switch (kpd.key[i].kstate) {  // Report active key state : IDLE, PRESSED, HOLD, or RELEASED
                        case PRESSED:
                            msg = " 按下.";
                            OnKeyPress(kpd.key[i].kchar);
                            break;
                        case HOLD:
                            msg = " 按住.";
                            OnKeyPress(kpd.key[i].kchar);
                            break;
                        case RELEASED:
                            msg = " 释放.";
                            Keyboard.release(100);
                            break;
                        case IDLE:
                            msg = " IDLE.";
                    }
                    Serial.print("Key ");
                    Serial.print(kpd.key[i].kchar);
                    Serial.println(msg);
                }
            }
        }


    }

}